package gov.nasa.anml.lifted;

import java.util.ArrayList;
import java.util.List;

import gov.nasa.anml.PDDL;
import gov.nasa.anml.State;
import gov.nasa.anml.utility.SimpleObject;
import gov.nasa.anml.utility.SimpleString;

public abstract class ScopedIdentifierImp<L,R extends SimpleObject<? super R>> extends ScopeImp implements Identifier<L,R> {

	public SimpleString name=SimpleString.Empty;
	public int id;

	public ScopedIdentifierImp() {}
	public ScopedIdentifierImp(Scope parent) {super(parent);}
	
	public ScopedIdentifierImp(Scope parent, SimpleString n) {init(parent,n);}
	public final void init(Scope parent, SimpleString n) {
		super.init(parent);
		this.name = n;
	}
	
	
	public ScopedIdentifierImp(Scope parent, SimpleString n, int id) {init(parent,n,id);}
	public final void init(Scope parent, SimpleString n, int id) {
		super.init(parent);
		this.name = n;
		this.id = id;
	}
	
	public final Identifier<L,R> id(int id) {
		this.id = id;
		return this;
	}

	public final int id() {
		return this.id;
	}

	public final SimpleString name() {
		return this.name;
	}

	public final Identifier<L,R> name(SimpleString name) {
		this.name = name;
		return this;
	}
	
	public int compareTo(Identifier<L,R> i) {
		return name.compareTo(i.name());
	}

	public History<R> storage(State p, State c) {
		return null;
	}

	public L value(State s) {
		return null;
	}

	public boolean apply(State p, int contextID, State c) {
		return false;
	}

	
	// Scoped Identifiers do not typically have values as float expressions
	// or, for that matter, as boolean expressions, except actions
	// which exhibit that behavior due to also existing as CompoundTime
	// Domain does not, despite CompoundTime, because Domain is all of time
	// so the only reasonable value would be 'true', which is nonetheless not
	// a float expression
	// maybe change name to realPDDL or refRealPDDL or refFloatPDDL ?
	// (RealNumber is too verbose...)
	public void translateDecl(PDDL pddl, Interval unit) {
	}	
	public void translateStmt(PDDL pddl, Interval unit, PDDL.Time time) {
		ExpressionImp.translateStmt(this,pddl,unit,time);
	}
	public PDDL.Expression translateExpr(PDDL pddl, Interval unit) {
		return pddl.FalseRef;
	}
	public PDDL.Argument translateArgument(PDDL pddl, Interval unit) {
		return pddl.NullRef;
	}
	public PDDL.Expression translateLValue(PDDL pddl, Interval unit) {
		return pddl.TrueRef;
	}
	
	/* for extends IdentifierImp implements Scope
	 * 
	public SymbolTable<Type<?>> types = new SymbolTable<Type<?>>();
	public SymbolTable<Constant<?>> cFluents = new SymbolTable<Constant<?>>();
	public SymbolTable<ConstantFunction<?>> cFunctions = new SymbolTable<ConstantFunction<?>>();
	public SymbolTable<Fluent<?>> fluents = new SymbolTable<Fluent<?>>();
	public SymbolTable<FluentFunction<?>> fluentFunctions = new SymbolTable<FluentFunction<?>>();
	public SymbolTable<Parameter<?>> parameters = new SymbolTable<Parameter<?>>();
	public SymbolTable<Action> actions = new SymbolTable<Action>(); 
	
	public HashMap<SimpleString, IdentifierImp> symbols = new HashMap<SimpleString,IdentifierImp>();
	
	public ArrayList<Statement> statements = new ArrayList<Statement>(); 
	// array would be more efficient, especially in the case of actions.
	// but lots of things can be tweaked for processing, so probably there
	// should exist stages of action representation anyways.
	// If so, then it is a bit easier at the high level to have more mutable
	// structures -- and the final level can do int fID, Statement[] statements,
	// etc.
	
	public ScopedIdentifierImp() {
		super();
	}
	public ScopedIdentifierImp(SimpleString n, int i) {
		super(n, i);
	}
	public ScopedIdentifierImp(SimpleString n) {
		super(n);
	}

	public Identifier addSymbol(IdentifierImp s) {
		return symbols.put(s.name,s);
	}
	
	public Identifier getSymbol(SimpleString s) {
		return symbols.get(s);
	}


	public <T extends SimpleObject<? super T>> Parameter<T> addParameter(Parameter<T> t) {
		symbols.put(t.name,t);
		return (Parameter<T>) parameters.put(t);
	}
	
	public <T extends SimpleObject<? super T>> Type<T> addType(Type<T> t) {
		symbols.put(t.name,t);
		return (Type<T>) types.put(t);
	}

	public <T extends SimpleObject<? super T>> Constant<T> addConstant(Constant<T> c) {
		symbols.put(c.name,c);
		return (Constant<T>) cFluents.put(c);
	}

	public <T extends SimpleObject<? super T>> ConstantFunction<T> addConstantFunction(ConstantFunction<T> c) {
		symbols.put(c.name,c);
		return (ConstantFunction<T>) cFunctions.put(c);
	}

	public <T extends SimpleObject<? super T>> Fluent<T> addFluent(Fluent<T> f) {
		symbols.put(f.name,f);
		return (Fluent<T>) fluents.put(f);
	}

	public <T extends SimpleObject<? super T>> FluentFunction<T> addFluentFunction(FluentFunction<T> f) {
		symbols.put(f.name,f);
		return (FluentFunction<T>) fluentFunctions.put(f);
	}

	public Action addAction(Action a) {
		symbols.put(a.name,a);
		return actions.put(a);
	}

	public SimpleString getParameterName(int p) {
		return parameters.getName(p);
	}
	
	public SimpleString getTypeName(int t) {
		return types.getName(t);
	}

	public SimpleString getConstantFluentName(int c) {
		return cFluents.getName(c);
	}
	
	public SimpleString getConstantFunctionName(int c) {
		return cFunctions.getName(c);
	}

	public SimpleString getFluentName(int f) {
		return fluents.getName(f);
	}

	public SimpleString getFunctionName(int f) {
		return fluentFunctions.getName(f);
	}

	public SimpleString getActionName(int a) {
		return actions.getName(a);
	}

	public Parameter<?> getParameter(int p) {
		return parameters.get(p);
	}
	
	public Type<?> getType(int t) {
		return types.get(t);
	}

	public Constant<?> getConstant(int c) {
		return cFluents.get(c);
	}

	public ConstantFunction<?> getConstantFunction(int c) {
		return cFunctions.get(c);
	}

	public Fluent<?> getFluent(int f) {
		return fluents.get(f);
	}

	public FluentFunction<?> getFluentFunction(int f) {
		return fluentFunctions.get(f);
	}

	public Action getAction(int a) {
		return actions.get(a);
	}

	public Parameter<?> getParameter(SimpleString p) {
		return parameters.get(p);
	}
	
	public Type<?> getType(SimpleString t) {
		return types.get(t);
	}

	public Constant<?> getConstant(SimpleString c) {
		return cFluents.get(c);
	}

	public ConstantFunction<?> getConstantFunction(SimpleString c) {
		return cFunctions.get(c);
	}

	public Fluent<?> getFluent(SimpleString f) {
		return fluents.get(f);
	}
	
	public FluentFunction<?> getFluentFunction(SimpleString f) {
		return fluentFunctions.get(f);
	}

	public Action getAction(SimpleString a) {
		return actions.get(a);
	}
	*/
}
